package simulator.srcv6;

import simulator.srcv6.TxRxEvent.TxRxEventType;

public class TxRxSystem {

    // Parametros da simulação
	private int MAX_DATA;//  = 100;
	
	private int DATA_SIZE;// = 100;
	private double INTERVAL = 0.250;
	private double PROBERROR;
	private double RITMO_BINARIO;// = 1000000.0;
	private int WINDOW;
	//final static double DISTANCIA     = 5000000.0;
	private double DISTANCIA;//     = 1000*1000;
	static double vp=200000000.0; // vp = 2e8 m/s.
	private Counter count;
	// Contadores Estatisticos	
    static double delayQ   = 0.0;
	static double delayQtx = 0.0;
	static double delaySys = 0.0;
	private String experienciename;
	private double timestampACK =0.0;

	private String filename;
	
	
	public TxRxSystem(String filename,String experiencename, int MAX_DATA,int DATA_SIZE, double RITMO_BINARIO, double DISTANCIA, double PROBERROR, int WINDOW ) {
		this.filename = filename;
		this.experienciename = experiencename;
		this.MAX_DATA = MAX_DATA;
		this.DATA_SIZE = DATA_SIZE;
		this.RITMO_BINARIO = RITMO_BINARIO;
		this.DISTANCIA = DISTANCIA;
		this.PROBERROR = PROBERROR;
		this.WINDOW = WINDOW;
	}
	public void execute() {
		Simulator.setLogLevel(Simulator.LogLevel.FULLDEBUG);	

		//Simulator.setDataFile("/home/rdi/Desktop/data.txt");
		//Simulator.setDataFile("C:/Users/Stephane/Desktop/data.txt");
		String s="#Simulation Results \n";
		s=s+"#Ntramas \t"+MAX_DATA+"\n";
		s=s+"#L \t\t"+DATA_SIZE+"\n";
		s=s+"#TaxaChegadas \t"+INTERVAL+"\n";
		s=s+"#Rb \t\t"+RITMO_BINARIO+"\n";
		s=s+"#d \t\t"+DISTANCIA+"\n";		
		Simulator.data(s);
		count = new Counter(experienciename,this.filename);
//		count.setAAndTrrt(DISTANCIA, RITMO_BINARIO, DATA_SIZE, vp);
//		count.setW(WINDOW);
		count.totalframes(MAX_DATA);
		
		/* Variáveis de estado - participantes no sistema */
		Source     source   = new Source(MAX_DATA, DATA_SIZE, INTERVAL);
		Receiver   receiver = new Receiver(DISTANCIA,count,PROBERROR, WINDOW);
		Transmiter transmiter    = new Transmiter(RITMO_BINARIO, DISTANCIA,WINDOW);
			
		/* Evento que arranca a simulação - abertura do serviço no instante 0.0 */
		TxRxEvent seed = new TxRxEvent(0.0, TxRxEventType.Generate_DATA, null);
		Simulator.addEvent(seed);

		/* Evento actual - o que se está a processar em cada ciclo */
		TxRxEvent current = (TxRxEvent)Simulator.nextEvent();

		/* Ciclo central da simulação */
		while (current!=null) {
			
			switch ((TxRxEvent.TxRxEventType)(current.type())) {
			    // Processamento de cada um dos tipos de acontecimentos
				case Generate_DATA:
					source.generateData(current);
					break;
					
				case Arrival_DATA:
					transmiter.arrivalData((Data)current.data());
					break;
					
				case StopTX:
					transmiter.stopTx((Data)current.data());
					break;
					
				case StartRX:
					receiver.startRX((Data)(current.data()));
					break;
				
				case StopRX:
					receiver.stopRX((Data)(current.data()));
					break;
					
				case ARRIVAL_ACK:
					timestampACK= current.timeStamp;
					transmiter.arrivalACK((Data)(current.data()));
					break;	
				
				case TIMEOUT:
					transmiter.timeout((Data)(current.data()));
					break;	
			}					
			/* Retira da lista o próximo acontecimento */
			current = (TxRxEvent) Simulator.nextEvent();	
		}
		Simulator.info("FIM.");
		count.setTimeStamp(this.timestampACK);
		count.setAvgDelaySys(delaySys/(double)MAX_DATA);
		// Impressão dos resultados da simulação.
		Simulator.info("STATS.");
		s = "Avg. delayQ = "+(delayQ/(double)MAX_DATA)+"\n";
		s = s+"Avg. delayQTx = "+(delayQtx/(double)MAX_DATA)+"\n";
		s = s+"Avg. delaySys = "+(delaySys/(double)MAX_DATA)+"\n";
		s = s+"Numero medio de tramas na fila, Nq = "+(delayQ/Simulator.getClock())+"\n";
		s = s+"Numero medio de tramas na fila ou a transmitir, Nqtx = "+(delayQtx/Simulator.getClock())+"\n";
		s = s+"Numero medio de tramas no sistema total, Nsistema = "+(delaySys/Simulator.getClock())+"\n";
		s = s+"Numero de timeout ="+Simulator.getTimeout();
		Simulator.info(s);
		count.writeToExcel();
	}
		
	public static void main(String[] args) {
		
		experiencia1();
		experiencia2();
		experiencia3();

	
	}

	private static void experiencia1() {
		String filename = "experiencia_1.xls";
		int max_data = 10000;
		double ritmoBinario=1000000;
		int datasize=100;
		double distancia = 1000*1000;
		int window1 = 127;
		int window2 = 127;
		
		new TxRxSystem(filename,"Pe-10-8_W=1", max_data, datasize, ritmoBinario, distancia, 0.00000001, window1).execute();
		new TxRxSystem(filename,"Pe-10-7_W=1", max_data, datasize, ritmoBinario, distancia, 0.0000001, window1).execute();
		new TxRxSystem(filename,"Pe-10-6_W=1", max_data, datasize, ritmoBinario, distancia, 0.000001, window1).execute();
		new TxRxSystem(filename,"Pe-10-5_W=1", max_data, datasize, ritmoBinario, distancia, 0.00001, window1).execute();
		new TxRxSystem(filename,"Pe-10-4_W=1", max_data, datasize, ritmoBinario, distancia, 0.0001, window1).execute();
		new TxRxSystem(filename,"Pe-10-3_W=1", max_data, datasize, ritmoBinario, distancia, 0.001, window1).execute();
		
		new TxRxSystem(filename,"Pe-10-8_W=127", max_data, datasize, ritmoBinario, distancia, 0.00000001, window2).execute();
		new TxRxSystem(filename,"Pe-10-7_W=127", max_data, datasize, ritmoBinario, distancia, 0.0000001, window2).execute();
		new TxRxSystem(filename,"Pe-10-6_W=127", max_data, datasize, ritmoBinario, distancia, 0.000001, window2).execute();
		new TxRxSystem(filename,"Pe-10-5_W=127", max_data, datasize, ritmoBinario, distancia, 0.00001, window2).execute();
		new TxRxSystem(filename,"Pe-10-4_W=127", max_data, datasize, ritmoBinario, distancia, 0.0001, window2).execute();
		new TxRxSystem(filename,"Pe-10-3_W=127", max_data, datasize, ritmoBinario, distancia, 0.001, window2).execute();
		
		
	}
	private static void experiencia2() {
		String filename = "experiencia_2.xls";
		double ritmoBinario=1000000;
		double probErro=0.000001;
		double distancia1 = 10*1000;
		double distancia2 =1000*1000;
		double distancia3= 10000 *1000;
		int window = 127;
		int max_data = 10000;
		
		new TxRxSystem(filename,"L100_d10km", max_data, 100, ritmoBinario, distancia1, probErro, window).execute();
		new TxRxSystem(filename,"L1.000_d10km", max_data, 1000, ritmoBinario, distancia1, probErro, window).execute();
		new TxRxSystem(filename,"L10.000_d10km", max_data, 10000, ritmoBinario, distancia1, probErro, window).execute();
		new TxRxSystem(filename,"L100.000_d10km", max_data, 100000, ritmoBinario, distancia1, probErro, window).execute();
		new TxRxSystem(filename,"L1.000.000_d10km", max_data, 1000000, ritmoBinario, distancia1, probErro, window).execute();
		
		new TxRxSystem(filename,"L100_d1000km", max_data, 100, ritmoBinario, distancia2, probErro, window).execute();
		new TxRxSystem(filename,"L1.000_d1000km", max_data, 1000, ritmoBinario, distancia2, probErro, window).execute();
		new TxRxSystem(filename,"L10.000_d1000km", max_data, 10000, ritmoBinario, distancia2, probErro, window).execute();
		new TxRxSystem(filename,"L100.000_d1000km", max_data, 100000, ritmoBinario, distancia2, probErro, window).execute();
		new TxRxSystem(filename,"L1.000.000_d1000km", max_data, 1000000, ritmoBinario, distancia2, probErro, window).execute();
		
		new TxRxSystem(filename,"L100_d10.000km", max_data, 100, ritmoBinario, distancia3, probErro, window).execute();
		new TxRxSystem(filename,"L1.000_d10.000km", max_data, 1000, ritmoBinario, distancia3, probErro, window).execute();
		new TxRxSystem(filename,"L10.000_d10.000km", max_data, 10000, ritmoBinario, distancia3, probErro, window).execute();
		new TxRxSystem(filename,"L100.000_d10.000km", max_data, 100000, ritmoBinario, distancia3, probErro, window).execute();
		new TxRxSystem(filename,"L1.000.000_d10.000km", max_data, 1000000, ritmoBinario, distancia3, probErro, window).execute();
		
	}
	
	private static void experiencia3() {
		String filename = "experiencia_3.xls";
		int max_data = 10000;
		
		double ritmoBinario=1000000;
		int datasize=100;
		double distancia = 1000*1000;
		
		double probErro1=0.0001;
		double probErro2=0.001;
		
		new TxRxSystem(filename,"W=1_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 1).execute();
		new TxRxSystem(filename,"W=3_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 3).execute();
		new TxRxSystem(filename,"W=7_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 7).execute();
		new TxRxSystem(filename,"W=15_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 15).execute();
		new TxRxSystem(filename,"W=63_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 63).execute();
		new TxRxSystem(filename,"W=127_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 127).execute();
		new TxRxSystem(filename,"W=255_Pe-10-4", max_data, datasize, ritmoBinario, distancia, probErro1, 255).execute();
		
		new TxRxSystem(filename,"W=1_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 1).execute();
		new TxRxSystem(filename,"W=3_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 3).execute();
		new TxRxSystem(filename,"W=7_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 7).execute();
		new TxRxSystem(filename,"W=15_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 15).execute();
		new TxRxSystem(filename,"W=63_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 63).execute();
		new TxRxSystem(filename,"W=127_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 127).execute();
		new TxRxSystem(filename,"W=255_Pe-10-3", max_data, datasize, ritmoBinario, distancia, probErro2, 255).execute();

		
		
	}
}
